/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.test; 

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicConnection;
import javax.jms.TopicConnectionFactory;
import javax.jms.TopicPublisher;
import javax.jms.TopicSession;
import javax.jms.TopicSubscriber;

import cgl.narada.jms.NBJmsInitializer;

public class SubscriptionTester implements javax.jms.MessageListener{
  private TopicSession pubSession;
  private TopicSession subSession;
  private TopicPublisher publisher;
  private TopicConnection connection;
  private String userName;
  
  public SubscriptionTester(Properties connectionProperties, 
			    String transportType, String userName) 
    throws Exception {
    NBJmsInitializer ini;
    this.userName = userName;
    ini = new NBJmsInitializer(connectionProperties, transportType); 
    // Lookup a JMS connection factory
    TopicConnectionFactory conFactory =
      (TopicConnectionFactory)ini.lookup();   
    initializeChatSession(conFactory, userName);
  }
  
  public void initializeChatSession(TopicConnectionFactory conFactory,
				    String username) 
    throws Exception {
    // Create a JMS connection
    TopicConnection connection =
      conFactory.createTopicConnection("guest","password");
    
    // Create a JMS session object
    TopicSession pubSession =
      connection.createTopicSession(false,
				    Session.AUTO_ACKNOWLEDGE);
    TopicSession subSession =
      connection.createTopicSession(false,
				    Session.AUTO_ACKNOWLEDGE);
    
    String topicString = "/streams/chat/private/Text";
    // Lookup a JMS topic
    Topic chatTopic = 
      pubSession.createTopic(topicString);  
    
    System.out.println("Will be publishing to topic [" + topicString + "]" );
    // Create a JMS publisher and subscriber
    TopicPublisher publisher = 
      pubSession.createPublisher(chatTopic);
    TopicSubscriber subscriber = 
      subSession.createSubscriber(chatTopic);
    
    // Set a JMS message listener
    subscriber.setMessageListener(this);
    
    // Intialize the Chat application
    set(connection, pubSession, subSession, publisher, username);
    
    // Start the JMS connection; allows messages to be delivered
    connection.start();
  }
  
  public void startConnection() throws JMSException {
    connection.start();
  }
  
  public void stopConnection() throws JMSException {
    connection.stop();
  }
  
  /* Initializes the instance variables */
  public void set(TopicConnection con, TopicSession pubSess,
		  TopicSession subSess, TopicPublisher pub, 
		  String username) {
    this.connection = con;
    this.pubSession = pubSess;
    this.subSession = subSess;
    this.publisher = pub;
    this.userName = username;
  }

  /* Receive message from topic subscriber */
  public void onMessage(Message message) {
    try {
      TextMessage textMessage = (TextMessage) message;
      String text = textMessage.getText();
      System.out.println(text + "@" + userName);
    } catch(JMSException jmse){ jmse.printStackTrace(); }
  }
  
  /* Create and send message using topic publisher */
  protected void writeMessage(String text)throws JMSException {
    int numOfMessages = 1;
    long start = System.currentTimeMillis();
   
    TextMessage message = pubSession.createTextMessage();
    message.setText("[" + userName+"] : "+ text );
    publisher.publish(message);
  }
  
  /* Close the JMS connection */
  public void close() throws JMSException {
    connection.close();
  }
  /* Run the Chat client */
  public static void main(String [] args){
    try{
      if(args.length!= 3) {
	System.out.println("Usage: java cgl.narada.test.Chat <hostName> " +
			   "<portNum> <numOfUsers>");
	System.exit(0);
      } 
      System.out.println("Type h for usage options");
      Properties props = new Properties();
      /** These properties pertain to setting up a TCP, udp and multicast
	  link */
      props.put("hostname", args[0]); /** for both tcp, udp*/
      props.put("portnum", args[1]);  /** for both tcp, udp */
      props.put("TCPServerPort", "0"); /** for TCP */
      
      int numOfUsers = Integer.parseInt(args[2]);
      String userName = "Jack";
      SubscriptionTester chat;
 
      SubscriptionTester[] chatters = new SubscriptionTester[numOfUsers];
      for (int i=0; i < numOfUsers; i++) {
	chatters[i]=  new SubscriptionTester(props, 
					     "tcp", userName + " (" + i +")");
      }
      chat = chatters[0];
      
      // read from command line
      BufferedReader commandLine = new 
	java.io.BufferedReader(new 
	  InputStreamReader(System.in));
      
      // loop until the word "exit" is typed
      while(true){
	String s = commandLine.readLine();
	if (s == null) {
	  chat.close();
	  break;
	}
	if (s.equalsIgnoreCase("h")) {
	  System.out.println("Simply type messages for normal chat");
	  System.out.println("<stop> Stop the connection. Messages cached");
	  System.out.println("<start> Starts connection. Cache released");
	  continue;
	}
	if (s.equalsIgnoreCase("start")) {
	  chat.startConnection();
	  continue;
	}
	if (s.equalsIgnoreCase("stop")) {
	  chat.stopConnection();
	  continue;
	}
	if(s.equalsIgnoreCase("exit")){
	  chat.close(); // close down connection
	  break;
	  //System.exit(0);// exit program
	}
	
	chat.writeMessage(s);
      }/** end while-true */
      System.out.println("Chat: exiting ");
    }catch(Exception e){ 
      e.printStackTrace(); 
    }
  } /** end-main */
}
